# Module aem.two_d.transient.base -- base class for transient single-layer two-d elements
#
# Copyright (c) 2000, V.Kelson and M.Bakker
#           (c) 2001, Willem Jan Zaadnoordijk

import copy
import types
from math import sqrt
from numpy import *

import geometry.xy
XY = geometry.xy.XY

import aem.container
RowList = aem.container.RowList
ColumnList = aem.container.ColumnList
import aem.matrix

from aem.two_d.single import base


class Element(base.Element):
	'''Base class for transient analytic elements

	based on single.base.Element
	- adds AquiferDiffusivity method
	- overwrites Solve method'''

	def aquiferDiffusivity(self,xy,t):
		'''Returns aquiferDiffusivity at point xy at time t

		For nearly all elements but Aquifer elements this is
		achieved by calling the 'parent' element. Must be overloaded
		for Aquifer element'''
		assert isinstance(xy,XY),"XY argument is required"
		return self.parent.aquiferDiffusivity(xy,t)

	def solve(self,t=0,factor=1.0,elementList=None):
		'''Compute solution directly

		A solution is compiled to determine the change of the parameters
		with respect to the current value of the parameters. The factor
		may be set to less than one for relaxation of the solution
		The solution is either determined for the initial steady state or
		for the transient elements. For a transient solve the time should
		be larger than the previous time of solving (or zero when it is the
		first transient solve)
		Procedure:
		Compile full matrix for all elements in elementList
		Call aem.matrix.Solver(rows) for full solution
		Pass solution back to elements'''

		if t <= 0 :
			# solve initial steady state
			self.initialSteadyState.solve()
		else :
			# transient solve
			if not(self.givenElement):
				if elementList :
					solutionList = elementList
				else :
					# exclude first element being the initial steady state
					solutionList = self.elementList[1:len(self.elementList)]
				rows = []
				columns = []
				for e in solutionList:
					mr,mc = e.getMatrixContribution(solutionList,t)
					rows = rows + mr
					columns = columns + mc
				s = aem.matrix.Solver(rows)
				x = s.solve()
				# Add solution to current value of parameter
				for i in range(len(x)):
					columns[i].element.parameters[columns[i].index] = \
						factor * x[i][0] + \
						columns[i].element.parameters[columns[i].index]

	def extractionInfluence(self,t):
		ext=[]
		for el in self.elementList :
			ext=ext+el.extractionInfluence(t)
		return RowList( ext )
